#include "my_lex.h"

// 初始化
void My_lex::init(){
    // 初始化DFA
    // 初始状态
    dfa.add_state("q0");
    dfa.set_initial("q0");
    // Ident: letter + non_letter
    dfa.add_state("q1");
    for (char ch = 'a'; ch <= 'z'; ch++)
    {
        dfa.add_transition("q0", ch, "q1");
    }
    for (char ch = 'A'; ch <= 'Z'; ch++)
    {
        dfa.add_transition("q0", ch, "q1");
    }
    dfa.add_transition("q0", '_', "q1");
    for (char ch = 'a'; ch <= 'z'; ch++)
    {
        dfa.add_transition("q1", ch, "q1");
    }
    for (char ch = 'A'; ch <= 'Z'; ch++)
    {
        dfa.add_transition("q1", ch, "q1");
    }
    for (int i = 0; i < 10; i++)
    {
        dfa.add_transition("q1", '0' + i, "q1");
    }
    dfa.add_transition("q1", '_', "q1");
    dfa.add_state("q2", true, true, "ID");
    for (char ch = 'a'; ch <= 'z'; ch++)
    {
        dfa.add_non_transition("q1", ch, "q2");
    }
    for (char ch = 'A'; ch <= 'Z'; ch++)
    {
        dfa.add_non_transition("q1", ch, "q2");
    }
    for (int i = 0; i < 10; i++)
    {
        dfa.add_non_transition("q1", '0' + i, "q2");
    }
    dfa.add_non_transition("q1", '_', "q2");
    // NUM: num + num
    dfa.add_state("q3");
    for (int i = 0; i < 10; i++)
    {
        dfa.add_transition("q0", '0' + i, "q3");
    }
    for (int i = 0; i < 10; i++)
    {
        dfa.add_transition("q3", '0' + i, "q3");
    }
    dfa.add_state("q4", true, true, "NUMBER");
    for (int i = 0; i < 10; i++)
    {
        dfa.add_non_transition("q3", '0' + i, "q4");
    }
    // ;
    dfa.add_state("q5", true, false, "\';\'");
    dfa.add_transition("q0", ';', "q5");
    // (
    dfa.add_state("q6", true, false, "\'(\'");
    dfa.add_transition("q0", '(', "q6");
    // )
    dfa.add_state("q7", true, false, "\')\'");
    dfa.add_transition("q0", ')', "q7");
    // ,
    dfa.add_state("q8", true, false, "\',\'");
    dfa.add_transition("q0", ',', "q8");
    // {
    dfa.add_state("q9", true, false, "\'{\'");
    dfa.add_transition("q0", '{', "q9");
    // }
    dfa.add_state("q10", true, false, "\'}\'");
    dfa.add_transition("q0", '}', "q10");
    // ||
    dfa.add_state("q11");
    dfa.add_transition("q0", '|', "q11");
    dfa.add_state("q12", true, false, "\'||\'");
    dfa.add_transition("q11", '|', "q12");
    // &&
    dfa.add_state("q13");
    dfa.add_transition("q0", '&', "q13");
    dfa.add_state("q14", true, false, "\'&&\'");
    dfa.add_transition("q13", '&', "q14");
    // +
    dfa.add_state("q15", true, false, "\'+\'");
    dfa.add_transition("q0", '+', "q15");
    // -
    dfa.add_state("q16", true, false, "\'-\'");
    dfa.add_transition("q0", '-', "q16");
    // *
    dfa.add_state("q17", true, false, "\'*\'");
    dfa.add_transition("q0", '*', "q17");
    // %
    dfa.add_state("q18", true, false, "\'%\'");
    dfa.add_transition("q0", '%', "q18");
    // < and <=
    dfa.add_state("q19");
    dfa.add_transition("q0", '<', "q19");
    dfa.add_state("q20", true, false, "\'<=\'");   // <=
    dfa.add_transition("q19", '=', "q20");
    dfa.add_state("q21", true, true, "\'<\'");     // <
    dfa.add_non_transition("q19", '=', "q21");
    // > and >=
    dfa.add_state("q22");
    dfa.add_transition("q0", '>', "q22");
    dfa.add_state("q23", true, false, "\'>=\'");   // >=
    dfa.add_transition("q22", '=', "q23");
    dfa.add_state("q24", true, true, "\'>\'");     // <
    dfa.add_non_transition("q22", '=', "q24");
    // ! and !=
    dfa.add_state("q25");
    dfa.add_transition("q0", '!', "q25");
    dfa.add_state("q26", true, false, "\'!=\'");   // !=
    dfa.add_transition("q25", '=', "q26");
    dfa.add_state("q27", true, true, "\'!\'");     // !
    dfa.add_non_transition("q25", '=', "q27");
    // = and ==
    dfa.add_state("q28");
    dfa.add_transition("q0", '=', "q28");
    dfa.add_state("q29", true, false, "\'==\'");   // ==
    dfa.add_transition("q28", '=', "q29");
    dfa.add_state("q30", true, true, "\'=\'");     // =
    dfa.add_non_transition("q28", '=', "q30");
    // / and // and /*
    dfa.add_state("q31");
    dfa.add_transition("q0", '/', "q31");
    dfa.add_state("q32", true, false, "\'//\'");   // //
    dfa.add_transition("q31", '/', "q32");
    dfa.add_state("q33", true, false, "\'/*\'");   // /*
    dfa.add_transition("q31", '*', "q33");
    dfa.add_state("q34", true, true, "\'/\'");     // /
    dfa.add_non_transition("q31", '/', "q34");
    dfa.add_non_transition("q31", '*', "q34");
    // 初始化保留字表
    reserve_.insert("int");
    reserve_.insert("if");
    reserve_.insert("else");
    reserve_.insert("while");
    reserve_.insert("break");
    reserve_.insert("continue");
    reserve_.insert("return");
    reserve_.insert("void");
    //dfa.print();
}

// 读入文本
void My_lex::get_input(std::string &input){
    input_ = input;
}

bool My_lex::reserve(std::string content){
    // 比较保留字表
    return reserve_.find(content) != reserve_.end();
}

void My_lex::jump_blank(){
    // 跳过空格，准备读有效字符
    while(ptr < input_.size() && input_[ptr] == ' ' || input_[ptr] == '\n' || input_[ptr] == '\t'){
        if(input_[ptr] == '\n'){
            line_num_++;
        }
        ptr++;
    }
}

bool My_lex::jump_anno(){
    // 跳过注释
    while(ptr < input_.length()){
        while(input_[ptr] != '*')
        {
            ptr++;
            if(input_[ptr] == '\n'){
                line_num_++;
            }
        }
        ptr++;
        if(input_[ptr] == '\n'){
            line_num_++;
        }
        if (input_[ptr] == '/')
        {
            ptr++;
            return true;
        }
    }
    return false;
}

void My_lex::jump_line(){
    while(input_[ptr] != '\n'){
        ptr++;
    }
    ptr++;
    line_num_++;
}

// 得到下一个token
bool My_lex::next_token(Token *result){
    int len = 0;
    while (!dfa.get_current()->isFinal && ptr + len < input_.length())
    {
        if(!dfa.next(input_[ptr + len])){
            std::cerr << "Wrong token" << input_.substr(ptr, len) << std::endl;
            return false;
        }
        len++;
    }
    if(ptr + len >= input_.length() && !dfa.get_current()->isFinal){
        if(!dfa.get_current()->isFinal){
            std::cerr << "Wrong token" << input_.substr(ptr, len - 1) << std::endl;
            return false;
        }
    }
    if(dfa.get_current()->need_retract){
        len--;
    }
    std::string content = input_.substr(ptr, len);
    // 处理注释
    if(content == "/*"){
        if(!jump_anno()){
            std::cerr << "Wrong annonation!" << std::endl;
            return false;
        }
        dfa.reset();
        jump_blank();
        return true;
    }
    if(content == "//"){
        jump_line();
        dfa.reset();
        jump_blank();
        return true;
    }
    // 设置result
    result->content = std::string("\"") + content + std::string("\"");
    result->num = num_++;
    result->line_num = line_num_;
    if (reserve(content))
    {
        result->type = std::string("\'") + content + std::string("\'");
    }
    else
    {
        result->type = dfa.get_current()->type;
    }
    // 准备下一次token扫描
    ptr += len;
    dfa.reset();
    jump_blank();

    return true;
}

// 分析整个文本
bool My_lex::analysis(std::vector<Token*> &result){
    if(ptr < input_.length()){
        jump_blank();
    }
    while (ptr < input_.length())
    {
        Token *token = new Token;
        if(!next_token(token)){
            return false;
        }
        if(!token->content.empty()){
            result.push_back(token);
        }
        else{
            delete token;
        }
    }
    return true;
}

void My_lex::print(std::vector<Token *> &result){
    for (auto token : result)
    {
        std::cout << token->num << ":" << token->type << ":" << token->content << ":" << token->line_num << std::endl;
    }
}
